#include "stdafx.h"
#include "OpCodeMap.h"
#include <map>

bool GetOpCode(BYTE opByte, CString & opCodeStr)
{
    switch (opByte)
    {
    case 0xCC:
        opCodeStr = StrInterrupt + StrSpace + _T("3");
        break;
    case 0x64:
        opCodeStr = StrFS;
        break;
    case 0x25:
        opCodeStr = StrAnd + StrSpace + StrEAX + StrComma + StrImm32;
        break;
    case 0x89:
        opCodeStr = StrMov + StrSpace + StrRegMem32 + StrComma + StrReg32;
    	break;
    case 0x8B:
        opCodeStr = StrMov + StrSpace + StrReg32 + StrComma + StrRegMem32;
        break;
    case 0xA1:
        opCodeStr = StrMov + StrSpace + StrEAX + StrComma + StrSegOffset32;
        break;
    case 0xA3:
        opCodeStr = StrMov + StrSpace + StrSegOffset32 + StrComma + StrEAX;
        break;
    case 0xC6:
        opCodeStr = StrMov + StrSpace + StrRegMem8 + StrComma + StrImm8;
        break;
    case 0x88:
        opCodeStr = StrMov + StrSpace + StrRegMem8 + StrComma + StrReg8;
        break;
    case 0x8A:
        opCodeStr = StrMov + StrSpace + StrReg8 + StrComma + StrRegMem8;
        break;
    case 0x6A:
        opCodeStr = StrPush + StrSpace + StrImm8;
        break;
    case 0x68:
        opCodeStr = StrPush + StrSpace + StrImm32;
        break;
    case 0x83:
        opCodeStr = StrNeedModConfirm;
        break;
    case 0x81:
        opCodeStr = StrNeedModConfirm;
        break;
    case 0x80:
        opCodeStr = StrNeedModConfirm;
        break;
    case 0x33:
        opCodeStr = StrXor + StrSpace  + StrReg32 + StrComma + StrRegMem32;
        break;
    case 0x32:
        opCodeStr = StrXor + StrSpace  + StrReg8 + StrComma + StrRegMem8;
        break;
    case 0x8D:
        opCodeStr = StrLea + StrSpace  + StrReg32 + StrComma + StrRegMem32;
        break;
    case 0xE8:
        opCodeStr = StrCall + StrSpace  + StrRel32;
        break;
    case 0x38:
        opCodeStr = StrCmp + StrSpace  + StrRegMem8 + StrComma + StrReg8;
        break;
    case 0x3B:
        opCodeStr = StrCmp + StrSpace  + StrReg32 + StrComma + StrRegMem32;
        break;
    case 0x3C:
        opCodeStr = StrCmp + StrSpace  + StrAL + StrComma + StrImm8;
        break;
    case 0x3D:
        opCodeStr = StrCmp + StrSpace  + StrEAX + StrComma + StrImm32;
        break;
    case 0x39:
        opCodeStr = StrCmp + StrSpace  + StrRegMem32 + StrComma + StrReg32;
        break;
    case 0x72:
      opCodeStr = StrJB + StrSpace  + StrRel8;
      break;
    case 0x74:
        opCodeStr = StrJE + StrSpace  + StrRel8;
        break;
    case 0x75:
        opCodeStr = StrJNE + StrSpace  + StrRel8;
        break;
    case 0xEB:
        opCodeStr = StrJMP + StrSpace  + StrRel8;
        break;
    case 0xE9:
        opCodeStr = StrJMP + StrSpace  + StrRel32;
        break;
    case 0xFF:
        opCodeStr = StrNeedModConfirm;
        break;
    case 0xFE:
        opCodeStr = StrNeedModConfirm;
        break;
    case 0xF7:
        opCodeStr = StrNeedModConfirm;
        break;
    case 0xC7:
        opCodeStr = StrNeedModConfirm;
        break;
    case 0xD0:
      opCodeStr = StrNeedModConfirm;
      break;
    case 0x03:
      opCodeStr = StrAdd + StrSpace + StrReg32 + StrComma + StrRegMem32;
      break;
    case 0xC9:
        opCodeStr = StrMov + StrSpace + StrEAX + StrComma + StrEAX;// leave? no need to deal with.
        break;
    case 0x0F:
        opCodeStr = StrNeedMoreOperandCode;
        break;
    case 0xF0:
      opCodeStr = StrMov + StrSpace + StrEAX + StrComma + StrEAX;//Lock 
      break;
    case 0xF3:
      opCodeStr = StrNeedMoreOperandCode;
      break;
    case 0x66:
        opCodeStr = StrPtrOverride;
        break;
    case 0x7E:
      opCodeStr = StrJNB + StrSpace + StrRel8;
      break;
    case 0xC3:
        opCodeStr = StrRet;
        break;
    case 0xC2:
        opCodeStr = StrRet + StrSpace + StrImm16;
        break;
    case 0x85:
        opCodeStr = StrTest + StrSpace + StrRegMem32 + StrComma + StrReg32;
        break;
    case 0x84:
        opCodeStr = StrTest + StrSpace + StrRegMem8 + StrComma + StrReg8;
        break;
    case 0xA9:
        opCodeStr = StrTest + StrSpace + StrEAX + StrComma + StrImm32;
        break;
    case 0x0C:
        opCodeStr = StrOR + StrSpace + StrAL + StrComma + StrImm8;
        break;
    case 0x0B:
        opCodeStr = StrOR + StrSpace + StrReg32 + StrComma + StrRegMem32;
        break;
    case 0x77:
        opCodeStr = StrJA + StrSpace + StrRel8;
        break;
    case 0x76:
        opCodeStr = StrJBE + StrSpace + StrRel8;
        break;
    case 0x2B:
        opCodeStr = StrSub + StrSpace + StrReg32 + StrComma + StrRegMem32;
        break;
    case 0x1B:
        opCodeStr = StrSbb + StrSpace + StrReg32 + StrComma + StrRegMem32;
        break;
    case 0xF9:
      opCodeStr = StrSTC + StrSpace;
    case 0xC1:
      opCodeStr = StrNeedModConfirm;
      break;
    case 0x73:
      opCodeStr = StrJNB + StrSpace + StrRel8;
      break;
    case 0x7D:
      opCodeStr = StrJNB + StrSpace + StrRel8;
      break;
    case 0x6B:
      opCodeStr = StrIMUL + StrSpace + StrReg32 + StrComma + 
        StrRegMem32 + StrComma + StrImm8;
      break;
    default:
        {
            if (opByte <= 0x57 && opByte >= 0x50)
            {
                opByte -= 0x50;
                opByte = opByte << 3;
                CString strReg;
                PraseModRMReg(opByte, strReg);
                opCodeStr = StrPush + StrSpace + strReg;
                break;
            }
            else if (opByte <= 0x5F && opByte >= 0x58)
            {
                opByte -= 0x58;
                opByte = opByte << 3;
                CString strReg;
                PraseModRMReg(opByte, strReg);
                opCodeStr = StrPop + StrSpace + strReg;
                break;
            }
            else if (opByte <= 0xBF && opByte >= 0xB8)
            {
                opByte -= 0xB8;
                opByte = opByte << 3;
                CString strReg;
                PraseModRMReg(opByte, strReg);
                opCodeStr = StrMov + StrSpace + strReg + StrComma + StrImm32;
                break;
            }
            else if (opByte <= 0x47 && opByte >= 0x40)
            {
                opByte -= 0x40;
                opByte = opByte << 3;
                CString strReg;
                PraseModRMReg(opByte, strReg);
                opCodeStr = StrInc + StrSpace + strReg;
                break;
            }
            else if (opByte <= 0xB7 && opByte >= 0xB0)
            {
              opByte -= 0xB0;
              opByte = opByte << 3;
              CString strReg;
              PraseModRMReg(opByte, strReg);
              MapReg32To8(strReg);
              opCodeStr = StrMov + StrSpace + strReg + StrComma + StrImm8;
              break;
            }
        }
        opCodeStr = _T("Not Supported Operand...");
        return false;
    }
    return true;
}

bool GetExtendedOpCode(BYTE opByte, BYTE modRM, CString & opCodeStr)
{
    switch (opByte)
    {
    case 0x83:
        {
            BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
            if(regByte == 5)
                opCodeStr = StrSub + StrSpace + StrRegMem32 + StrComma + StrImm8;
            else if(regByte == 0)
                opCodeStr = StrAdd + StrSpace + StrRegMem32 + StrComma + StrImm8;
            else if(regByte == 4)
                opCodeStr = StrAnd + StrSpace + StrRegMem32 + StrComma + StrSigExt8;
            else if(regByte == 7)
                opCodeStr = StrCmp + StrSpace + StrRegMem32 + StrComma + StrImm8;
            else if(regByte == 1)
              opCodeStr = StrOR + StrSpace + StrRegMem32 + StrComma + StrImm8;
            else
            {
                opCodeStr = _T("Not Supported Operand...");
                return false;
            }
            break;    
        }
    case 0x81:
        {
            BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
            if(regByte == 4)
                opCodeStr = StrAnd + StrSpace + StrRegMem32 + StrComma + StrImm32;
            else if(regByte == 5)
                opCodeStr = StrSub + StrSpace + StrRegMem32 + StrComma + StrImm32;
            else if(regByte == 7)
              opCodeStr = StrCmp + StrSpace + StrRegMem32 + StrComma + StrImm32;
            else if(regByte == 0)
              opCodeStr = StrAdd + StrSpace + StrRegMem32 + StrComma + StrImm32;
            else
            {
                opCodeStr = _T("Not Supported Operand...");
                return false;
            }
            break;    
        }
    case 0x80:
        {
            BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
            if(regByte == 7)
                opCodeStr = StrCmp + StrSpace + StrRegMem8 + StrComma + StrImm8;
            else if (regByte == 0)
                opCodeStr = StrAdd + StrSpace + StrRegMem8 + StrComma + StrImm8;
            else if (regByte == 1)
              opCodeStr = StrOR + StrSpace + StrRegMem8 + StrComma + StrImm8;
            else
            {
                opCodeStr = _T("Not Supported Operand...");
                return false;
            }
            break;    
        }
    case 0xFF:
        {
            BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
            if(regByte == 2)  
                opCodeStr = StrCall + StrSpace + StrRegMem32;
            else if(regByte == 3)     
                opCodeStr = _T("Not Supported Operand...");
            else if(regByte == 4)     
                opCodeStr = StrJMP + StrSpace + StrRegMem32;
            else if(regByte == 6)     
                opCodeStr = StrPush + StrSpace + StrRegMem32;
            else if(regByte == 0)     
              opCodeStr = StrInc + StrSpace + StrRegMem32;
            else if(regByte == 1)     
              opCodeStr = StrDec + StrSpace + StrRegMem32;
            else
            {
                opCodeStr = _T("Not Supported Operand...");
                return false;
            }
            break;    
        }
    case 0xFE:
        {
            BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
            if(regByte == 0)  
                opCodeStr = StrInc + StrSpace + StrRegMem8;
            else
            {
                opCodeStr = _T("Not Supported Operand...");
                return false;
            }
            break;    
        }
    case 0xF7:
        {
            BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
            if(regByte == 0)  
                opCodeStr = StrTest + StrSpace + StrRegMem32 + StrComma + StrImm32;
            else if(regByte == 3)  
                opCodeStr = StrNeg + StrSpace + StrRegMem32;
            else
            {
                opCodeStr = _T("Not Supported Operand...");
                return false;
            }
            break;    
        }
    case 0xC7:
        {
            BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
            if(regByte == 0)  
                opCodeStr = StrMov + StrSpace + StrRegMem32 + StrComma + StrImm32;
            else
            {
                opCodeStr = _T("Not Supported Operand...");
                return false;
            }
            break;    
        }
    case 0x0F:
        {
           switch (modRM)
           {
           case 0x84:
               opCodeStr = StrJE + StrSpace + StrRel32;
               break;
           case 0x85:
               opCodeStr = StrJNE + StrSpace + StrRel32;
               break;
           case 0x83:
               opCodeStr = StrJNB + StrSpace + StrRel32;// JNB, JAE
               break;
           case 0x82:
             opCodeStr = StrJB + StrSpace + StrRel32;// JNB, JAE
             break;
           case 0x87:
             opCodeStr = StrJA + StrSpace + StrRel32;// JNB, JAE
             break;
           case 0x8C:
             opCodeStr = StrJB + StrSpace + StrRel32;// JNB, JAE
             break;
           case 0xB6:
               opCodeStr = StrMovZX + StrSpace +StrReg32 + StrComma + StrRegMem8;// JNB, JAE
               break;
           case 0xB7:
               opCodeStr = StrMovZX + StrSpace +StrReg32 + StrComma + StrRegMem16;// JNB, JAE
               break;
           case 0x95:
               opCodeStr = StrSetNE + StrSpace + StrRegMem8;
               break;
           case 0x34:
               opCodeStr = StrMov + StrSpace + StrEAX + StrComma + StrEAX;// sysenter? no need to deal with.
               break;
           case 0x94:
               opCodeStr = StrSetE + StrSpace + StrRegMem8;
               break;
           case 0xB1:
             opCodeStr = StrCMPXCHG + StrSpace + StrRegMem32 + StrComma + StrReg32;
             break;
           default:
               opCodeStr = _T("Not Supported Jcc Operand...");
               return false;
           }
           break; 
        }
    case 0xD0:
      {
        BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
        if(regByte == 6) // not on manual.... Just add this.
          opCodeStr = StrSAL + StrSpace + StrRegMem8 + StrComma + _T("1");
        else
        {
          opCodeStr = _T("Not Supported Operand...");
          return false;
        }
        break;    
      }
    case 0xC1:
      {
        BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
        if(regByte == 5)
          opCodeStr = StrSHR + StrSpace + StrRegMem32 + StrComma + StrImm8;
        else if(regByte == 4)
          opCodeStr = StrSAL + StrSpace + StrRegMem32 + StrComma + StrImm8;
        else
        {
          opCodeStr = _T("Not Supported Operand...");
          return false;
        }
        break;    
      }
    case 0xF3:
      {
        switch (modRM)
        {
        case 0xAB:
          opCodeStr = StrREP + StrSpace + StrSTOS + StrSpace + StrDWORDPTR + 
            StrSpace + StrOpenBracket + StrEDI + StrCloseBracket + StrComma + StrEAX;
          break;
        default:
          opCodeStr = _T("Not Supported Jcc Operand...");
          return false;
        }
        break; 
      }
    default:
        opCodeStr = _T("Not Supported Operand...");
        return false;
    }
    return true;
}

void PraseModRMReg(BYTE modRM, CString& regStr)
{
    BYTE regByte = (modRM & 0x38) >> 3; // Get Byte 3-5 00111000
    switch (regByte)
    {
    case 0:
        regStr = StrEAX;
        break;
    case 1:
        regStr = StrECX;
        break;
    case 2:
        regStr = StrEDX;
        break;
    case 3:
        regStr = StrEBX;
        break;
    case 4:
        regStr = StrESP;
        break;
    case 5:
        regStr = StrEBP;
        break;
    case 6:
        regStr = StrESI;
        break;
    case 7:
        regStr = StrEDI;
        break;
    default:
        regStr = _T("Not Supported Reg Value...");
        break;
    }
}

void PraseModRMEffAddr(BYTE modRM, CString& effAddrStr)
{
    BYTE modByte = (modRM & 0xC0) >> 6; // Get Byte 6-7 11000000
    BYTE rmByte    = modRM & 0x07; // Get Byte 0-2 00000111
    switch (modByte)
    {
    case 0:
        switch (rmByte)
        {
        case 0:
            effAddrStr = StrOpenBracket + StrEAX + StrCloseBracket;
            break;
        case 1:
            effAddrStr = StrOpenBracket + StrECX + StrCloseBracket;
            break;
        case 2:
            effAddrStr = StrOpenBracket + StrEDX + StrCloseBracket;
            break;
        case 3:
            effAddrStr = StrOpenBracket + StrEBX + StrCloseBracket;
            break;
        case 4:
            effAddrStr = StrSIB;
            break;
        case 5:
            effAddrStr = StrDisp32;
            break;
        case 6:
            effAddrStr = StrOpenBracket + StrESI + StrCloseBracket;
            break;
        case 7:
            effAddrStr = StrOpenBracket + StrEDI + StrCloseBracket;
            break;
        default:
            effAddrStr = _T("Not Supported Effective Address...");
            break;
        }
        break;
    case 1:
        switch (rmByte)
        {
        case 0:
            effAddrStr = StrDisp8 + StrOpenBracket + StrEAX + StrCloseBracket;
            break;
        case 1:
            effAddrStr = StrDisp8 + StrOpenBracket + StrECX + StrCloseBracket;
            break;
        case 2:
            effAddrStr = StrDisp8 + StrOpenBracket + StrEDX + StrCloseBracket;
            break;
        case 3:
            effAddrStr = StrDisp8 + StrOpenBracket + StrEBX + StrCloseBracket;
            break;
        case 4:
            effAddrStr = StrDisp8 + StrSIB;
            break;
        case 5:
            effAddrStr = StrDisp8 + StrOpenBracket + StrEBP + StrCloseBracket;
            break;
        case 6:
            effAddrStr = StrDisp8 + StrOpenBracket + StrESI + StrCloseBracket;
            break;
        case 7:
            effAddrStr = StrDisp8 + StrOpenBracket + StrEDI + StrCloseBracket;
            break;
        default:
            effAddrStr = _T("Not Supported Effective Address...");
            break;
        }
        break;
    case 2:
        switch (rmByte)
        {
        case 0:
            effAddrStr = StrDisp32 + StrOpenBracket + StrEAX + StrCloseBracket;
            break;
        case 1:
            effAddrStr = StrDisp32 + StrOpenBracket + StrECX + StrCloseBracket;
            break;
        case 2:
            effAddrStr = StrDisp32 + StrOpenBracket + StrEDX + StrCloseBracket;
            break;
        case 3:
            effAddrStr = StrDisp32 + StrOpenBracket + StrEBX + StrCloseBracket;
            break;
        case 4:
            effAddrStr = StrDisp32 + StrSIB;
            break;
        case 5:
            effAddrStr = StrDisp32 + StrOpenBracket + StrEBP + StrCloseBracket;
            break;
        case 6:
            effAddrStr = StrDisp32 + StrOpenBracket + StrESI + StrCloseBracket;
            break;
        case 7:
            effAddrStr = StrDisp32 + StrOpenBracket + StrEDI + StrCloseBracket;
            break;
        default:
            effAddrStr = _T("Not Supported Effective Address...");
            break;
        }
        break;
    case 3:
        switch (rmByte)
        {
        case 0:
            effAddrStr = StrEAX;
            break;
        case 1:
            effAddrStr = StrECX;
            break;
        case 2:
            effAddrStr = StrEDX;
            break;
        case 3:
            effAddrStr = StrEBX;
            break;
        case 4:
            effAddrStr = StrESP;
            break;
        case 5:
            effAddrStr = StrEBP;
            break;
        case 6:
            effAddrStr = StrESI;
            break;
        case 7:
            effAddrStr = StrEDI;
            break;
        default:
            effAddrStr = _T("Not Supported Effective Address...");
            break;
        }
        break;
     default:
        effAddrStr = _T("Not Supported Mod Value...");
        break;
    }
}

void PraseSIBBase(BYTE SIBByte, CString& SIBBaseStr)
{
    BYTE SIBBaseByte = SIBByte & 0x07; // Get Byte 0-2 00000111
    switch (SIBBaseByte)
    {
    case 0:
        SIBBaseStr = StrEAX;
        break;
    case 1:
        SIBBaseStr = StrECX;
        break;
    case 2:
        SIBBaseStr = StrEDX;
        break;
    case 3:
        SIBBaseStr = StrEBX;
        break;
    case 4:
        SIBBaseStr = StrESP;
        break;
    case 5:
        SIBBaseStr = StrOpenBracket + StrAsterisk + StrCloseBracket;
        break;
    case 6:
        SIBBaseStr = StrESI;
        break;
    case 7:
        SIBBaseStr = StrEDI;
        break;
    default:
        SIBBaseStr = _T("Not Supported SIB Base Value...");
        break;
    }
}


void PraseSIBScaleIndex(BYTE SIBByte, CString& SIBScaleIndexStr)
{
    BYTE SIBIndexByte =  (SIBByte & 0x38) >> 3; // Get Byte 3-5 00111000
    switch (SIBIndexByte)
    {
    case 0:
        SIBScaleIndexStr = StrOpenBracket + StrEAX + StrCloseBracket;
        break;
    case 1:
        SIBScaleIndexStr = StrOpenBracket + StrECX + StrCloseBracket;
        break;
    case 2:
        SIBScaleIndexStr = StrOpenBracket + StrEDX + StrCloseBracket;
        break;
    case 3:
        SIBScaleIndexStr = StrOpenBracket + StrEBX + StrCloseBracket;
        break;
    case 4: 
        SIBScaleIndexStr = StrNone;
        break;
    case 5:
        SIBScaleIndexStr = StrOpenBracket + StrEBP + StrCloseBracket;
        break;
    case 6:
        SIBScaleIndexStr = StrOpenBracket + StrESI + StrCloseBracket;
        break;
    case 7:
        SIBScaleIndexStr = StrOpenBracket + StrEDI + StrCloseBracket;
        break;
    default:
        SIBScaleIndexStr = _T("Not Supported SIB Index Value...");
        break;
    }

    BYTE SIBScaleByte = (SIBByte & 0xC0) >> 6; // Get Byte 6-7 11000000
    CString scaleStr;
    int iScaleFator = (int)(pow(2.0, SIBScaleByte));
    if(iScaleFator != 1 && SIBIndexByte != 4)
    {
        char scaleFactorChar[2];
        CString tempRepStr;
        switch (iScaleFator)
        {
        case 2:
        case 4:
        case 8:
            _itoa_s(iScaleFator, scaleFactorChar, 2, 10);
            tempRepStr = StrAsterisk + CString(scaleFactorChar) + StrCloseBracket;
            break;
        default:
            SIBScaleIndexStr = _T("Not Supported SIB Scale Value...");
            break;
        } 
        SIBScaleIndexStr.Replace(StrCloseBracket, tempRepStr);
    }           
}

bool MapReg32To8(CString & regStr)
{
    if(regStr.CompareNoCase(StrEAX) == 0)
        regStr = StrAL;
    else if(regStr.CompareNoCase(StrECX) == 0)
        regStr = StrCL;
    else if(regStr.CompareNoCase(StrEDX) == 0)
        regStr = StrDL;
    else if(regStr.CompareNoCase(StrEBX) == 0)
        regStr = StrBL;
    else
    {
        regStr = _T("Not Supported Reg Value...");
        return false;
    }
    return true;
}

bool MapReg32To16(CString & regStr)
{
    if(regStr.GetLength() == 3 &&
        regStr.Left(1).CompareNoCase(_T("E")) == 0)
        regStr = regStr.Right(2);
    else
    {
        regStr = _T("Not Supported Reg Value...");
        return false;
    }
    return true;
}

bool IsReg32(CString & regStr)
{
    if(regStr.CompareNoCase(StrEAX) == 0)
        return true;
    else if(regStr.CompareNoCase(StrECX) == 0)
        return true;
    else if(regStr.CompareNoCase(StrEDX) == 0)
        return true;
    else if(regStr.CompareNoCase(StrEBX) == 0)
        return true;
    else
        return false;
    return true;
}

bool IsMemAddrFormat(CString opCodeStr)
{
    if(opCodeStr.Find(StrOpenBracket) != -1)
        return true;
    return false;
}

bool FindInstructionDNA(const CString opCodeStr, CString DNAInstructionStr)
{
    if(opCodeStr.Find(DNAInstructionStr) != -1)
        return true;
    return false;
}